using System;
using System.Collections;
using System.Reflection;
using System.Threading;

namespace CI
{
    /// <summary>
    /// Static global constants and varibles
    /// </summary>
    public static class Globals
    {
        public const string IRobotControllerContract = "http://schemas.tempuri.org/2009/08/irobotcontroller.html";
        public const string MSRoboticEnvContract = "http://schemas.tempuri.org/2008/11/msroboticsenv.html";
        public const string NoFitnessFunction = "NOFITNESSFUNCTION";

        /// <summary>Scenario match</summary>
        public const string ScenarioMatch = ".scenario.xml";

        private static bool _isAlreadyRunningChecked;

        /// <summary> break time set to break out of proccessing </summary>
        public static TimeSpan BreakTime;

        /// <summary>restart simulation</summary>
        public static bool ContinousRestart = true;

        /// <summary>Critical Acquire Lock Timeout</summary>
        public static TimeSpan CriticalAcquireLockTimeout = new TimeSpan(0, 0, 60);

        /// <summary>Where was the app launched from</summary>
        public static LaunchType LaunchedFrom = LaunchType.Unknown;

        /// <summary>Mutex to keep track if we are already loaded</summary>
        private static Mutex _runningMutex;

        /// <summary>Startup robotics timeout</summary>
        public static TimeSpan StartupRoboticsTimeout = new TimeSpan(0, 5, 0);

        private static SimEnv _simEnv;
        private static SimEnv SimEnv
        {
            get { return _simEnv ?? (_simEnv = SimEnv.Instance); }
        }

        // todo totaly implemented wrong, this is bad......................... ever heard of enums?
        #region Binding entitys, eventually i want to make this discoverable

        /// <summary>Energy constant to identify the energy sypanse to be read</summary>
        public const string ENERGY = "energy";

        /// <summary>Energy constant to identify the energy sypanse to be read</summary>
        public const string ENERGYCHANGE = "energyChange";

        public const string IROBOTFORWARD = "IROBOTFORWARD";
        public const string IROBOTLEFTFRONTBUMPER = "IROBOTLEFTFRONTBUMPER";
        public const string IROBOTRIGHTFRONTBUMPER = "IROBOTRIGHTFRONTBUMPER";
        public const string IROBOTTURNLEFT = "IROBOTTURNLEFT";
        public const string IROBOTTURNRIGHT = "IROBOTTURNRIGHT";

        public const string CYCLOPS = "CYCLOPS";

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="interfaceType"></param>
        /// <returns></returns>
        public static ArrayList GetConcreteClasses(Type interfaceType)
        {
            // create our results list
            var interfaces = new ArrayList();

            // load the calling assembly
            var asm = Assembly.GetCallingAssembly();

            var typesInAssembly = asm.GetTypes();
            foreach (var type in typesInAssembly)
            {
                if (type.IsAbstract)
                    continue;

                if (null != type.GetInterface(interfaceType.FullName))
                {
                    // We found a type, load it
                    SimEnv.TraceLogger.LogDebug(string.Format("Assembly: {0} has a type {1} that implements {2}",
                                                       asm.ManifestModule.Name, type.FullName, interfaceType.FullName));

                    interfaces.Add(type.UnderlyingSystemType);
                }
            }

            return interfaces;
        }

        

        /// <summary>
        /// Detects if the app is already running and if so forces a shutdown
        /// </summary>
        public static bool IsAlreadyRunning()
        {
            bool result = false;

            // see if we have checked before
            if (_isAlreadyRunningChecked)
            {
                return false;
            }
            _isAlreadyRunningChecked = true;

            SimEnv.TraceLogger.LogDebug("Current Folder : " + Environment.CurrentDirectory);
            SimEnv.TraceLogger.LogDebug("Current User : " + Environment.UserName + ":" + Environment.UserInteractive);

            // create the running mutex
            _runningMutex = new Mutex(true, "Mesopotamia");
            // see if its running
            if (!_runningMutex.WaitOne(TimeSpan.Zero, true))
            {
                SimEnv.TraceLogger.LogDebug("IsAlready Running is exiting");
                result = true;
            }

            SimEnv.TraceLogger.LogDebug("Finished IsAlreadyRunning Result :" + result);

            return result;
        }
    }

    /// <summary>Organism Energy Delegate</summary>
    public delegate void SynapseIODelegate(Int64 inputValue);

    /// <summary>Neural network display mode</summary>
    public enum NeuralNetworkDisplayMode
    {
        Off,
        Indicitive,
        RealTime,
    }

    /// <summary>Child Synapse parent type</summary>
    public enum ChildSynapseIOParentType
    {
        SimpleVisionSystem,
    }

    /// <summary>Neural network display mode</summary>
    public enum SVSFormatType
    {
        GreyScale,
        Frequency,
    }
}